using System;
using System.Xml;
using System.Collections;
using System.Runtime.InteropServices;

namespace ScenarioFramework.Modules.PCM.DataModel.ConfigurationManager.Entity
{
	//*********************************************************************
	//
	// XmlEntities Class
	//
	// The XmlEntities class represents a collection base of XmlEntity
	// Its imports methods from WAPI.XmlObjectSet like get set and add
	// XmlEntities Has no fields
	//
	//*********************************************************************

	public class XMLEntities : bOSdotNET.XML.Data.XMLObjectSet 
	{
		public const string MAIN_NODE	= "Entities";

		public XMLEntities()
		{
			this.Init();
		}

		public XMLEntities(System.Xml.XmlNode nodeList)
		{
			this.Parse (nodeList);
		}

		override public void Init()
		{
			this.RemoveAll();
		}

		override public void Parse(System.Xml.XmlNode nodeList)
		{
			this.Init();

			System.Xml.XmlNode node;

			for ( int i=0; i<nodeList.ChildNodes.Count;i++)
			{
				node = nodeList.ChildNodes[i];

				switch ( node.Name) 
				{
					case XMLEntity.MAIN_NODE:
						this.Add ( new XMLEntity(node) );
						break;
				}
			}
		}

		public string GetShortXML()
		{
			bOSdotNET.XML.XMLNode xmlNode = new bOSdotNET.XML.XMLNode(XMLEntities.MAIN_NODE);
			XMLEntity xmlEntity = null;

			for ( int i=0; i<this.Count;i++)
			{
				xmlEntity = (XMLEntity)this[i];
				xmlNode.AddNode ( xmlEntity.GetShortXML() );
			}

			return xmlNode.GetXML(false, 0);
		}
		

		override public bOSdotNET.XML.XMLNode GetXMLNode()
		{
			bOSdotNET.XML.XMLNode xmlNode = new bOSdotNET.XML.XMLNode(XMLEntities.MAIN_NODE);

			for ( int i=0; i<this.Count;i++)
			{
				xmlNode.AddNode ( this[i].GetXMLNode() );
			}

			return xmlNode;
		}

		private string GetTest()
		{
			string Test;
			Test = "<Entities>";
			Test +=	 "<Entity Name=\"Entity1\">";
			Test +=	"<Description>aaaa</Description>";
			Test +=	"<Attributes>";
			Test +=	"<Attribute Name=\"Attr1\">";
			Test +=	"<Value>ddd</Value>";
			Test +=	"<Type>Type1</Type>";
			Test +=	"</Attribute>";
			Test +=	"</Attributes>";
			Test +=	"</Entity>";
			Test +=	"<Entity Name=\"Entity2\">";
			Test +=	"<Description>bbb</Description>";
			Test +=	"<Attributes>";
			Test +=	"<Attribute Name=\"Attr1\">";
			Test +=	"<Value>fff</Value>";
			Test +=	"<Type>Type2</Type>";
			Test +=	"</Attribute>";
			Test +=	"<Attribute Name=\"Attr2\">";
			Test +=	"<Value>rrr</Value>";
			Test +=	"<Type>Type3</Type>";
			Test +=	"</Attribute>";
			Test +=	"</Attributes>";
			Test +=	"</Entity>";
			Test +=	"</Entities>";

			return Test;
		}

		/** Method for return an entity from collection **/
		public XMLEntity Get(string sName)
		{
			XMLEntity entity = null;

			for ( int i=0; i<this.List.Count; i++)
			{
				entity = (XMLEntity)this.List[i];
				if ( entity.Name == sName )
				{
					return entity;
				}
			}

			throw new ScenarioFramework.Modules.PCM.DataModel.ConfigurationManager.Exception.EntityNotFound(sName + " not found.");
		}

		public XMLEntity GetById(string sId)
		{
			XMLEntity entity = null;

			for ( int i=0; i<this.List.Count; i++)
			{
				entity = (XMLEntity)this.List[i];
				if ( entity.Id == sId )
				{
					return entity;
				}
			}

			throw new ScenarioFramework.Modules.PCM.DataModel.ConfigurationManager.Exception.EntityNotFound(sId + " not found.");
		}



		/** Method for checking an entity in collection **/
		public bool AlmostIn(XMLEntities vValues)
		{
			XMLEntity leftEntity;
			XMLEntity rightEntity;

			for ( int i=0; i<this.List.Count; i++)
			{
				leftEntity = (XMLEntity)this.List[i];

				try
				{
					rightEntity = vValues.Get(leftEntity.Name);
				}
				catch ( ScenarioFramework.Modules.PCM.DataModel.ConfigurationManager.Exception.EntityNotFound)
				{
					return false;
				}
			}
			
			return true;
		}

		/** Method for checking an entity in collection **/
		public bool AlmostInByName (string sName)
		{
			XMLEntity Entity;

			for ( int i=0; i<this.List.Count; i++)
			{
				Entity = (XMLEntity)this.List[i];

				if (Entity.Name == sName)
				{
					return true;
				}
			}
			
			return false;
		}

		//= 0 OK
		//= 1 EntityA ready Exists
		//= 2 Attribute already exists
		public int AddEntityAttribute(string sEntity, string sAttribute, string sValue)
		{
			XMLEntity entity = null;
			XMLEntityAttribute attribute = null;
			for ( int i=0; i<this.Count; i++)
			{
				entity = (XMLEntity)this[i];

				if ( entity.Name.CompareTo ( sEntity) == 0 )
				{
					for ( int j=0; j<entity.XMLEntityAttributes.Count;j++)
					{
						attribute = (XMLEntityAttribute)entity.XMLEntityAttributes[j];
						if ( attribute.Name.CompareTo (sAttribute) == 0 ) 
						{
							return 2;
						}
					}
					attribute = new XMLEntityAttribute ();
					attribute.Name = sAttribute;
					attribute.Value = sValue;
					entity.XMLEntityAttributes.Add ( attribute);

					return 1;
				}
			}

			entity = new XMLEntity (sEntity);
			attribute = new XMLEntityAttribute ();
			attribute.Name = sAttribute;
			attribute.Value = sValue;
			entity.XMLEntityAttributes.Add ( attribute);
			this.Add (entity);

			return 0;
		}

		public string GetEntityAttributeValue(string sEntityAttribute)
		{
			string sEntity = string.Empty;
			string sAttribute = string.Empty;
			this.GetEntityAndAttribute(sEntityAttribute, ref sEntity, ref sAttribute);

			XMLEntity entity = null;
			XMLEntityAttribute attribute = null;
			for ( int i=0; i<this.Count; i++)
			{
				entity = (XMLEntity)this[i];

				if ( entity.Name.CompareTo ( sEntity) == 0 )
				{
					for ( int j=0; j<entity.XMLEntityAttributes.Count;j++)
					{
						attribute = (XMLEntityAttribute)entity.XMLEntityAttributes[j];
						if ( attribute.Name.CompareTo (sAttribute) == 0 ) 
						{
							return attribute.Value;
						}
					}

					return string.Empty;
				}
			}

			return string.Empty;
		}

		public double GetEntityAttributeDoubleValue(string sEntityAttribute)
		{
			string sValue = this.GetEntityAttributeValue(sEntityAttribute);

			if ( sValue.CompareTo ( string.Empty ) == 0 )
			{
				return 0;
			}

			try
			{
				return Convert.ToDouble(sValue);
			}
			catch 
			{
				return 0;
			}
		}

		public int GetEntityAttributeIntValue(string sEntityAttribute)
		{
			string sValue = this.GetEntityAttributeValue(sEntityAttribute);

			if ( sValue.CompareTo ( string.Empty ) == 0 )
			{
				return 0;
			}

			try
			{
				return Convert.ToInt32(sValue);
			}
			catch 
			{
				return 0;
			}
		}



		public int SetEntityAttributeValue(string sEntityAttribute, string sValue)
		{
			string sEntity = string.Empty;
			string sAttribute = string.Empty;
			this.GetEntityAndAttribute(sEntityAttribute, ref sEntity, ref sAttribute);

			XMLEntity entity = null;
			XMLEntityAttribute attribute = null;
			for ( int i=0; i<this.Count; i++)
			{
				entity = (XMLEntity)this[i];

				if ( entity.Name.CompareTo ( sEntity) == 0 )
				{
					for ( int j=0; j<entity.XMLEntityAttributes.Count;j++)
					{
						attribute = (XMLEntityAttribute)entity.XMLEntityAttributes[j];
						if ( attribute.Name.CompareTo (sAttribute) == 0 ) 
						{
							attribute.Value = sValue;
							return 0;
						}
					}

					return 1;
				}
			}

			return 2;
		}

		public int SetOrAddEntityAttributeValue(string sEntityAttribute, string sValue)
		{
			string sEntity = string.Empty;
			string sAttribute = string.Empty;
			this.GetEntityAndAttribute(sEntityAttribute, ref sEntity, ref sAttribute);

			XMLEntity entity = null;
			XMLEntityAttribute attribute = null;
			for ( int i=0; i<this.Count; i++)
			{
				entity = (XMLEntity)this[i];

				if ( entity.Name.CompareTo ( sEntity) == 0 )
				{
					for ( int j=0; j<entity.XMLEntityAttributes.Count;j++)
					{
						attribute = (XMLEntityAttribute)entity.XMLEntityAttributes[j];
						if ( attribute.Name.CompareTo (sAttribute) == 0 ) 
						{
							attribute.Value = sValue;
							return 0;
						}
					}
					attribute = new XMLEntityAttribute();
					attribute.Name = sAttribute;
					attribute.Value = sValue;

					entity.XMLEntityAttributes.Add ( attribute );
					return 1;
				}
			}

			return 2;
		}



		/** method to remove an entity from collectio by its name**/
		public bool RemoveByName(string sName)
		{
			XMLEntity Entity;

			for ( int i=0; i<this.List.Count; i++)
			{
				Entity = (XMLEntity)this.List[i];

				if (Entity.Name == sName)
				{
					this.List.Remove(Entity);
					return true;
				}
			}
			
			return false;
		}

		public int CopyAttributeFrom(XMLEntities source, string sEntity, string sAttribute)
		{
			XMLEntity entity2Add = null;
			try
			{
				entity2Add = this.Get (sEntity);
			}
			catch ( ScenarioFramework.Modules.PCM.DataModel.ConfigurationManager.Exception.EntityNotFound )
			{
				entity2Add = new XMLEntity(sEntity);
				this.Add (entity2Add);
			}

			//Aggiungo l'attributo e le sue proprieta
			XMLEntity entity2Copy = null;
			try
			{
				entity2Copy = source.Get (entity2Add.Name);
			}
			catch ( ScenarioFramework.Modules.PCM.DataModel.ConfigurationManager.Exception.EntityNotFound ) 
			{
				throw;
			}

			XMLEntityAttribute attribute2Copy = null;
			try
			{
				attribute2Copy = entity2Copy.XMLEntityAttributes.Get (sAttribute);
			}
			catch ( ScenarioFramework.Modules.PCM.DataModel.ConfigurationManager.Exception.EntityAttributeNotFound ) 
			{
				throw;
			}

			return entity2Add.XMLEntityAttributes.Add(attribute2Copy);
		}


		/** Method for filling the entities widthout calling WAPI first **/
		public void ReadFromConfiguration()
		{
			String sEntities=string.Empty;

#if _PCM_TEST_
			sEntities = GetTest();

#else
			ScenarioFramework.Modules.PCM.DataModel.ConfigurationManager.PCMWAPIResponse response = new ScenarioFramework.Modules.PCM.DataModel.ConfigurationManager.PCMWAPIResponse();

			try
			{
				sEntities = XMLEntities.GetEntities (ref response);
			}
			catch (System.Exception  e)
			{
				System.Console.WriteLine (e.Message );

				throw new Exception.ConfigurationError (e.Message);
			}
			if ( response.iCode != 0 )
			{
				throw new Exception.ConfigurationError ( response.sMsg);
			}
#endif
			this.Parse (sEntities);
		}

		/** SORTING  FIELDS **/

		public enum SortFields 
		{
			Name,
			EntityAggregation,
			Description
		}

		/** SORTING METHODS **/


		public void Sort(SortFields sortField, bool isAscending) 
		{
			switch (sortField) 
			{
				case SortFields.Name:
					InnerList.Sort(new NameComparer());
					break;
				case SortFields.EntityAggregation:
					InnerList.Sort(new EntityAggregationComparer());
					break;
				case SortFields.Description:
					InnerList.Sort(new DescriptionComparer());
					break;
			}
			if (!isAscending) InnerList.Reverse();
		}


		private sealed class NameComparer : IComparer 
		{
			public int Compare(object x, object y) 
			{
				XMLEntity first = (XMLEntity) x;
				XMLEntity second = (XMLEntity) y;
				return first.Name.CompareTo(second.Name);
			}
		}

		private sealed class EntityAggregationComparer : IComparer 
		{
			public int Compare(object x, object y) 
			{
				XMLEntity first = (XMLEntity) x;
				XMLEntity second = (XMLEntity) y;
				return first.EntityAggregation.CompareTo(second.EntityAggregation);
			}
		}

		private sealed class DescriptionComparer : IComparer 
		{
			public int Compare(object x, object y) 
			{
				XMLEntity first = (XMLEntity) x;
				XMLEntity second = (XMLEntity) y;
				return first.Description.CompareTo(second.Description);
			}
		}

		[ DllImport( "ConfigurationManager.dll", EntryPoint="GetEntities")]
		public static extern String GetEntities(ref ScenarioFramework.Modules.PCM.DataModel.ConfigurationManager.PCMWAPIResponse response);

		public XMLEntityAttribute GetEntityAttribute(string sEntityName, string sAttributeName)
		{
			XMLEntity entity = null;
			XMLEntityAttribute attribute = null;

			try
			{
				entity = this.Get(sEntityName);
			}
			catch ( ScenarioFramework.Modules.PCM.DataModel.ConfigurationManager.Exception.EntityNotFound)
			{
				throw;
			}

			try
			{
				attribute = entity.XMLEntityAttributes.Get(sAttributeName);
			}
			catch ( ScenarioFramework.Modules.PCM.DataModel.ConfigurationManager.Exception.EntityAttributeNotFound) 
			{
				throw;
			}

			return attribute;
		}

		public XMLEntityAttribute GetEntityAndAttribute(string sEntityAttribute)
		{
			string sEntityName = string.Empty;
			string sAttributeName = string.Empty;

			this.GetEntityAndAttribute(sEntityAttribute, ref sEntityName, ref sAttributeName);

			return this.GetEntityAttribute(sEntityName, sAttributeName);
		}

		public void GetEntityAndAttribute(string Name, ref string EntityName, ref string AttributeName)
		{
			// extract position of "." and Entity - Attribute names 
			int IDX = Name.IndexOf(".",0);
			if (IDX <= 0)
			{
				EntityName= Name;
				AttributeName = string.Empty;
			}
			else
			{
				EntityName = Name.Substring(0,(IDX));
				AttributeName = Name.Substring(IDX+1);
			}
		}


	}
}